home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / applications / wp / xvi.lha / Xvi_V1.0_Src / startup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-04  |  10.0 KB  |  420 lines

  1. /* Copyright (c) 1990,1991,1992 Chris and John Downey */
  2. #ifndef lint
  3. static char *sccsid = "@(#)startup.c    2.3 (Chris & John Downey) 9/4/92";
  4. #endif
  5.  
  6. /***
  7.  
  8. * program name:
  9.     xvi
  10. * function:
  11.     PD version of UNIX "vi" editor, with extensions.
  12. * module name:
  13.     main.c
  14. * module function:
  15.     Entry point for xvi; setup, argument parsing and signal handling.
  16. * history:
  17.     STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  18.     Originally by Tim Thompson (twitch!tjt)
  19.     Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  20.     Heavily modified by Chris & John Downey
  21.  
  22. ***/
  23.  
  24. #include "xvi.h"
  25.  
  26. /*
  27.  * References to the current cursor position, and the window
  28.  * and buffer into which it references. These make the code a
  29.  * lot simpler, but we have to be a bit careful to update them
  30.  * whenever necessary.
  31.  */
  32. Buffer    *curbuf;
  33. Xviwin    *curwin;
  34.  
  35. /*
  36.  * Global variables.
  37.  */
  38. state_t        State = NORMAL;    /* This is the current state of the command */
  39.                 /* interpreter. */
  40.  
  41. unsigned    echo;        /*
  42.                  * bitmap controlling the verbosity of
  43.                  * screen output (see xvi.h for details).
  44.                  */
  45.  
  46. int        indentchars;    /* number of chars indented on current line */
  47.  
  48. volatile unsigned char
  49.         kbdintr;    /*
  50.                  * global flag set when a keyboard interrupt
  51.                  * is received
  52.                  */
  53.  
  54. bool_t        imessage;    /*
  55.                  * global flag to indicate whether we should
  56.                  * display the "Interrupted" message
  57.                  */
  58.  
  59. /*
  60.  * Internal routines.
  61.  */
  62. static    void    usage P((void));
  63.  
  64. Xviwin *
  65. xvi_startup(vs, argc, argv, envp)
  66. VirtScr    *vs;
  67. int    argc;
  68. char    *argv[];
  69. char    *envp;                /* init string from the environment */
  70. {
  71.     char    *tag = NULL;        /* tag from command line */
  72.     char    *pat = NULL;        /* pattern from command line */
  73.     long    line = -1;        /* line number from command line */
  74.     char    **files;
  75.     int        numfiles = 0;
  76.     int        count;
  77.     char    *env;
  78.     ignore_signals();
  79.  
  80.     /*
  81.      * Initialise parameter module.
  82.      */
  83.     init_params();
  84.  
  85.     /*
  86.      * Initialise yank/put module.
  87.      */
  88.     init_yankput();
  89.  
  90.     /*
  91.      * The critical path this code has to follow is quite tricky.
  92.      * We can't really run the "env" string until after we've set
  93.      * up the first screen window because we don't know what the
  94.      * commands in "env" might do: they might, for all we know,
  95.      * want to display something. And we can't set up the first
  96.      * screen window until we've set up the terminal interface.
  97.      *
  98.      * Also, we can't read the command line arguments until after
  99.      * we've run the "env" string because a "-s param=value" argument
  100.      * should override any setting of that parameter in the environment.
  101.      *
  102.      * All this means that the usage() function, which tells the
  103.      * user that the command line syntax was wrong, can only be
  104.      * called after the display interface has already been set up,
  105.      * which means we must be in visual mode. So usage() has to
  106.      * switch back to system mode (otherwise, on systems where
  107.      * sys_startv() & sys_endv() switch display pages,
  108.      * the user will never see the output of usage()). So ...
  109.      */
  110.  
  111.     /*
  112.      * Set up the first buffer and screen window.
  113.      * Must call sys_init first.
  114.      */
  115.     curbuf = new_buffer();
  116.     if (curbuf == NULL) {
  117.         sys_endv();
  118.         (void) fputs("Can't allocate buffer memory.\n", stderr);
  119.         sys_exit(2);
  120.     }
  121.     curwin = init_window(vs);
  122.     if (curwin == NULL) {
  123.         sys_endv();
  124.         (void) fputs("Can't allocate buffer memory.\n", stderr);
  125.         sys_exit(2);
  126.     }
  127.  
  128.     /*
  129.      * Connect the two together.
  130.      */
  131.     map_window_onto_buffer(curwin, curbuf);
  132.  
  133.     init_sline(curwin);
  134.  
  135.     /*
  136.      * Save a copy of the passed environment string in case it was
  137.      * obtained from getenv(), so that the subsequent call we make
  138.      * to get the SHELL parameter value does not overwrite it.
  139.      */
  140.     if (envp != NULL) {
  141.         env = strsave(envp);
  142.     } 
  143.     else {
  144.         env = NULL;
  145.     }
  146.  
  147.     /*
  148.      * Try to obtain a value for the "shell" parameter from the
  149.      * environment variable SHELL. If this is NULL, do not override
  150.      * any existing value. The system interface code (sys_init()) is
  151.      * free to set up a default value, and the initialisation string
  152.      * in the next part of the startup is free to override both that
  153.      * value and the one from the environment.
  154.      */
  155.     {
  156.     char    *sh;
  157.  
  158.     sh = getenv("SHELL");
  159.     if (sh != NULL)  set_param(P_shell, sh);
  160.     }
  161.  
  162.     /*
  163.      * Run any initialisation string passed to us.
  164.      *
  165.      * We can't really do this until we have set up the terminal
  166.      * because we don't know what the initialisation string might do.
  167.      */
  168.     if (env != NULL) {
  169.         register char    *ep;
  170.         register bool_t    escaped = FALSE;
  171.  
  172.     /*
  173.      * Commands in the initialization string can be
  174.      * separated by '|' (or '\n'), but a literal '|' or
  175.      * '\n' can be escaped by a preceding '\\', so we have
  176.      * to process the string, looking for all three
  177.      * characters.
  178.      */
  179.         for (ep = env; *ep;) {
  180.             switch (*ep++) {
  181.                 case '\\':
  182.                     escaped = TRUE;
  183.                     continue;
  184.                 case '|':
  185.                 case '\n':
  186.                     if (escaped) {
  187.                             register char *s, *d;
  188.  
  189.                             for (d = (s = --ep) - 1; (*d++ = *s++) != '\0'; )
  190.                             ;
  191.                     }
  192.                     else {
  193.                             ep[-1] = '\0';
  194.                          do_colon(env, FALSE);
  195.                          env = ep;
  196.                     }
  197.         /* fall through ... */
  198.                 default:
  199.                     escaped = FALSE;
  200.             }
  201.         }/*for ep */
  202.         if (ep > env) {
  203.             do_colon(env, FALSE);
  204.         }
  205.     }/*if env*/
  206.  
  207.     /*
  208.      * Process the command line arguments.
  209.      *
  210.      * We can't really do this until we have run the "env" string,
  211.      * because "-s param=value" on the command line should override
  212.      * parameter setting in the environment.
  213.      *
  214.      * This is a bit awkward because it means usage() is called
  215.      * when we're already in vi mode (which means, among other
  216.      * things, that display pages may have been swapped).
  217.      */
  218.     for (count = 1;
  219.      count < argc && (argv[count][0] == '-' || argv[count][0] == '+');
  220.                                 count++) {
  221.  
  222.         if (argv[count][0] == '-') {
  223.             switch (argv[count][1]) {
  224.                 case 't':
  225.         /*
  226.          * -t tag or -ttag
  227.          */
  228.                     if (numfiles != 0) usage();
  229.                     if (argv[count][2] != '\0') {
  230.                         tag = &(argv[count][2]);
  231.                     }
  232.                     else 
  233.                         if (count < (argc - 1)) {
  234.                             count += 1;
  235.                             tag = argv[count];
  236.                         }
  237.                         else {
  238.                             usage();
  239.                         }
  240.                     break;
  241.  
  242.                 case 's':
  243.         /*
  244.          * -s param=value or
  245.          * -sparam=value
  246.          */
  247.                     if (argv[count][2] != '\0') {
  248.                         argv[count] += 2;
  249.                     } 
  250.                     else 
  251.                         if (count < (argc - 1)) {
  252.                             count += 1;
  253.                         } 
  254.                         else {
  255.                             usage();
  256.                         }
  257.                     do_set(curwin, 1, &argv[count], FALSE);
  258.                     break;
  259.  
  260.                 default:
  261.                     usage();
  262.             }
  263.  
  264.         } 
  265.         else /* argv[count][0] == '+' */ {
  266.             char    nc;
  267.  
  268.         /*
  269.          * "+n file" or "+/pat file"
  270.          */
  271.             if (count >= (argc - 1)) usage();
  272.  
  273.             nc = argv[count][1];
  274.             if (nc == '/') {
  275.                 pat = &(argv[count][2]);
  276.             } 
  277.             else
  278.                 if (is_digit(nc)) {
  279.                     line = atol(&(argv[count][1]));
  280.                 } else 
  281.                     if (nc == '\0') {
  282.                         line = 0;
  283.                     } 
  284.                     else {
  285.                         usage();
  286.                     }
  287.             count += 1;
  288.             files = &argv[count];
  289.             numfiles = 1;
  290.         }/* else */
  291.     }
  292.     if (numfiles != 0 || tag != NULL) {
  293.     /*
  294.      * If we found "-t tag", "+n file" or "+/pat file" on
  295.      * the command line, we don't want to see any more
  296.      * file names.
  297.      */
  298.         if (count < argc) usage();
  299.     }
  300.     else {
  301.     /*
  302.      * Otherwise, file names are valid.
  303.      */
  304.             numfiles = argc - count;
  305.             if (numfiles > 0) {
  306.             files = &(argv[count]);
  307.             }
  308.     }
  309.  
  310.     /*
  311.      * Initialise the cursor and top of screen pointers
  312.      * to the start of the first buffer. Note that the
  313.      * bottom of screen pointer is also set up, as some
  314.      * code (e.g. move_window_to_cursor) depends on it.
  315.      */
  316.     curwin->w_topline = curbuf->b_file;
  317.     curwin->w_botline = curbuf->b_file->l_next;
  318.     move_cursor(curwin, curbuf->b_file, 0);
  319.     curwin->w_col = 0;
  320.     curwin->w_row = 0;
  321.  
  322.     /*
  323.      * Clear the window.
  324.      *
  325.      * It doesn't make sense to do this until we have a value for
  326.      * Pn(P_colour).
  327.      */
  328.     clear(curwin);
  329.  
  330.     if (numfiles != 0) {
  331.         if (line < 0 && pat == NULL)
  332.             echo = e_CHARUPDATE | e_SHOWINFO;
  333.  
  334.         do_next(curwin, numfiles, files, FALSE);
  335.  
  336.         if (pat != NULL) {
  337.             echo = e_CHARUPDATE | e_SHOWINFO | e_REGERR | e_NOMATCH;
  338.             (void) dosearch(curwin, pat, '/');
  339.         }
  340.         else if (line >= 0) {
  341.             echo = e_CHARUPDATE | e_SHOWINFO;
  342.             do_goto((line > 0) ? line : MAX_LINENO);
  343.         }
  344.  
  345.     } 
  346.     else if (tag != NULL) {
  347.         echo = e_CHARUPDATE | e_SHOWINFO | e_REGERR | e_NOMATCH;
  348.             if (do_tag(curwin, tag, FALSE, TRUE, FALSE) == FALSE) {
  349.         /*
  350.          * Failed to find tag - wait for a while
  351.          * to allow user to read tags error and then
  352.          * display the "no file" message.
  353.          */
  354.                 sleep(2);
  355.                 show_file_info(curwin);
  356.             }
  357.          } 
  358.          else {
  359.             echo = e_CHARUPDATE | e_SHOWINFO;
  360.             show_file_info(curwin);
  361.          }
  362.  
  363.     setpcmark(curwin);
  364.  
  365.     echo = e_CHARUPDATE;
  366.  
  367.     /*
  368.      * Ensure we are at the right screen position.
  369.      */
  370.     move_window_to_cursor(curwin);
  371.  
  372.     /*
  373.      * Draw the screen.
  374.      */
  375.     update_all();
  376.  
  377.     /*
  378.      * Update the cursor position on the screen, and go there.
  379.      */
  380.     cursupdate(curwin);
  381.     wind_goto(curwin);
  382.  
  383.     /*
  384.      * Allow everything.
  385.      */
  386.     echo = e_ANY;
  387.  
  388.     catch_signals();
  389.  
  390.     if (env != NULL) {
  391.         free(env);
  392.     }
  393.  
  394.     return(curwin);
  395. }
  396.  
  397. /*
  398.  * Print usage message and die.
  399.  *
  400.  * This function is only called after we have set the terminal to vi
  401.  * mode.
  402.  *
  403.  * The system interface functions have to ensure that it's safe to
  404.  * call sys_exit() when sys_endv() has already been called (& there
  405.  * hasn't necessarily been any intervening sys_startv()).
  406.  */
  407. static void
  408. usage()
  409. {
  410.     sys_endv();
  411.     (void) fputs("Usage: xvi { options } [ file ... ]\n", stderr);
  412.     (void) fputs("       xvi { options } -t tag\n", stderr);
  413.     (void) fputs("       xvi { options } +[num] file\n", stderr);
  414.     (void) fputs("       xvi { options } +/pat  file\n", stderr);
  415.     (void) fputs("\nOptions are:\n", stderr);
  416.     (void) fputs("       -s [no]boolean-parameter\n", stderr);
  417.     (void) fputs("       -s parameter=value\n", stderr);
  418.     sys_exit(1);
  419. }
  420.